// ProjectName: go-learn-demo
// PackageName: redisybxb
// Description:
// Author: hy.bai
// Date: 2025-08-31, 星期日 19:40

package redisybxb

import (
	"errors"
	"fmt"
	"log/slog"
	"strconv"
	"time"

	"github.com/redis/go-redis/v9"
)

// 开启一个事务
func RedisTxWatch() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 先设置一个值
	client.Set(*ctx, "counter", 0, 1*time.Minute)

	// 1.定义一个匿名的回调函数，用于处理事务逻辑。
	fn := func(tx *redis.Tx) error {
		// 获取被监控的key
		stringCmd := tx.Get(*ctx, "counter")
		// 判断是一个真实的报错，而且不是key值不存在
		scErr := stringCmd.Err()
		if scErr != nil && !errors.Is(scErr, redis.Nil) {
			return scErr
		}

		// 处理业务逻辑
		fmt.Println("旧值是：", stringCmd.Val())
		count, _ := strconv.Atoi(stringCmd.Val())
		count++
		pipeline := tx.Pipeline()
		statusCmd := pipeline.Set(*ctx, "counter", strconv.Itoa(count), 0)
		if statusCmd.Err() != nil {
			return statusCmd.Err()
		}
		// 提交事务
		_, txErr := pipeline.Exec(*ctx)
		return txErr
	}

	//  2.调用Watch方法，监听传入的key,同时绑定一个回调函数, 如果这个key没有被其他人进行写操作时，回调函数fn会执行。
	wErr := client.Watch(*ctx, fn, "counter")
	if wErr != nil {
		slog.Error(fmt.Sprintf("Redis Watch Error: %s", wErr.Error()))
	}

	stringCmd := client.Get(*ctx, "counter")
	fmt.Println("counter的新值是:", stringCmd.Val())
}

func TestTxWatch() {
	RedisTxWatch()
}
